home *** CD-ROM | disk | FTP | other *** search
/ Young Minds / Young Minds Interactive CD-ROM.ISO / crystal / cvmain.c < prev    next >
Encoding:
C/C++ Source or Header  |  1988-01-12  |  23.2 KB  |  872 lines

  1. /* cvmain.c
  2.  ************************************************************************/
  3.  
  4. #define    SHORT    50
  5.  
  6. #include    <stdio.h>
  7. #include    <string.h>
  8. #include    <fcntl.h>
  9. #include    "cvobj.h"
  10. #include    "cvlocs.h"
  11. #include    "cvocab.h"
  12. #include    "cvmsg.h"
  13. #include    "random.h"
  14. #include    "cvorcs.h"
  15. #include    "cvmisc.h"
  16. #include    "cvcode.h"
  17.  
  18. extern char etext;
  19. extern char edata;
  20. extern char end;
  21. extern char _etext;
  22. extern char _edata;
  23. extern char _end;
  24.  
  25. extern char *rmsg[] ;
  26. extern int actspk[] ;
  27. extern struct cmsg ctext[] ;
  28. extern struct cvocab vtab [] ;
  29. extern int maxloc ;
  30. extern void exit();
  31. extern void carry();
  32. extern void move();
  33. extern void move2();
  34. extern void destry();
  35. extern void getin();
  36. extern void juggle();
  37. extern void juggl2();
  38. extern void checkobj();
  39. extern void checkloc();
  40. extern void fixrmsg();
  41. extern void motd();
  42. extern void rspeak();
  43. extern void pspeak();
  44. extern void mspeak();
  45. extern void putcode();
  46. extern int yes();
  47. extern struct cvloc *moveme();
  48.  
  49. int saved = 0;    /* this defines the un-initialized state */
  50.  
  51. char *word1, *word2;
  52. char *vword, *oword;
  53.  
  54. struct cvobj *lastobj ;
  55. struct cvloc *loc = NULL;
  56. struct cvloc *newloc, *oldloc, *knfloc, *oldlc2;
  57. int    dflag = 0,
  58.     demo = 0,
  59.     score = 0,
  60.     mxscore = 0,
  61.     limit = 0,            /* how long his lamp will last on current power */
  62.     setup = 0,            /* state of setup */
  63.     tally = 0,            /* count of treasures yet to see */
  64.     tally2 = 0,            /* count of treasures you'll never see */
  65.     inorth = 0,        /* # of times he said NORTH instead of N */
  66.     detail = 0,        /* # of times we said "not allowed . .  */
  67.     numdie = 0,        /* # of times he died so far */
  68.     maxdie = 0,        /* # of ways to resurrect him */
  69.     holding = 0,        /* # objects he's carrying */
  70.     dkill = 0,            /* # of dwarves killed */
  71.     turns = 0,
  72.     nxtchr = 0,
  73.     abbnum = 0,        /* how often he gets long description */
  74.     clock1 = 0,        /* time from last treasure to closing */
  75.     clock2 = 0,        /* time from closing to closed */
  76.         /* LOGICALS FOLLOW */
  77.     bonus = FALSE,            /* gets bonus for correct finish */
  78.     closing = FALSE,        /* are we closing? */
  79.     panic = FALSE,            /* has he panicked */
  80.     wzdark = FALSE,
  81.     closed = FALSE,
  82.     gaveup = FALSE,
  83.     scoring = FALSE,
  84.     mltcmd = FALSE,
  85.     blklin = FALSE,
  86.     samvrb = FALSE,
  87.     finish = FALSE,
  88.     lmwarn = FALSE;
  89.  
  90.  
  91. struct monster orcs[] = {
  92.     {0},    /* spider */    /* monsters first */
  93.     {0},    /* dragon */
  94.     {0},    /* king */
  95.     {0},    /* djinni */
  96.     {0},    /* kobold */
  97.     {0},    /* bugbear */
  98.     {0},    /* unicorn */
  99.     {0},    /* giant orc */
  100.     {0},    /* balrog */
  101.     {62,1},    /* dwarf in pool hall */    /* dwarves next */
  102.     {78,1},    /* dwarf in privy chamber */
  103.     {85,1},    /* dwarf at window in secret passage */
  104.     {100,1},    /* dwarf in the time maze */
  105.     {126,1},    /* dwarf in the harem */
  106.     {130,1},    /* dwarf at the shelf */
  107.     {87},    /* pirate at where he hides his chest */    /* then these */
  108.     {0},    /* *YOU* */
  109.     {-1}};
  110.  
  111.  
  112. void
  113. locchg()
  114. {
  115.         if (dodwarf()) die();
  116. }
  117.  
  118. static void
  119. dohint(hint) register struct hint *hint;
  120. {
  121.     switch (hint-hints) {
  122.     case 4:    if (O_GATE->prop != 0 || HERE(WALLET)) hint->lc = 0;
  123.         break;
  124.     case 5: if (DAM->prop != 0) hint->lc = 0;
  125.         break;
  126.     case 6: if (holding <= 1 || loc->atloc.link != NULL ||
  127.                 oldlc2->atloc.link != NULL || oldloc->atloc.link != NULL)
  128.                 hint->lc = 0;
  129.         break;
  130.     } /* end of switch for special tests */
  131.     if (hint->lc == 0) return;
  132.     hint->lc = 0;
  133.     if (!yes(hint->quest,0,54)) return;
  134.     printf("I am prepared to give you a hint, but it will cost you %d \
  135. points.",hint->points);
  136.     hint->hinted = yes(175,hint->hmsg,54);
  137.     if (hint->hinted && limit>30) limit += 30*hint->points;
  138.     return;
  139. }
  140. void
  141. bug(num) int num;
  142. {    register long a;
  143.     (void) printf("\nFatal error number %d, see source code for\n\
  144. interpretation.\n",num);
  145.     a = *((long *) 1);
  146.     exit(1);
  147. }
  148.  
  149. void
  150. mkill(monster,object) register struct monster *monster;
  151.     register struct cvobj *object;
  152. {
  153.     object->prop = 0;
  154.     move(object,loc);
  155.     object->conn2.where = FIXED ;
  156.     monster->dseen = FALSE ;
  157.     monster->dloc = DEAD ;
  158. }
  159.  
  160. void
  161. showroom() {
  162.     putcode(( !(loc->abb++ % abbnum) || (loc->sdesc == NULL))
  163.                 ? loc->ldesc : loc->sdesc);
  164. }
  165.  
  166. void
  167. what(word) register int word;
  168. {    if (word && PCT(60)) {rspeak(60); return;}
  169.     if (PCT(20)) {rspeak(61); return;}
  170.     rspeak(13); return;
  171. }
  172.  
  173. static void
  174. capchk(word) register char *word;
  175. {
  176.     if (!strcmp(word,"indian")
  177.         || !strcmp(word,"persian")
  178.         || !strcmp(word,"coke")
  179.         || !strcmp(word,"kobold")
  180.         || !strcmp(word,"balrog")
  181.         || !strcmp(word,"sears")
  182.         || !strcmp(word,"rick") )
  183.     {    *word = toupper(*word);
  184.     }
  185. }
  186.  
  187. main(argc, argv)
  188. int argc;
  189. char * argv[];
  190. {
  191.     {    register int r;
  192.         if (!saved && argc == 2) {
  193.             cvinit(argc,argv);
  194.             exit(0);
  195.         } else if (argc != 1 || saved != 1) {
  196.             exit(1);
  197.         }
  198.     }
  199. /**********
  200.  * do initialization (some of it just in case):
  201.  * set all objects
  202.  *   nowhere (both ways)
  203.  *   to their initial properties
  204.  *   not linked to any location
  205.  * set all locations
  206.  *   to get long message next
  207.  *   to have flags = C_FORCED if there's a forced motion
  208.  ***********/
  209.     {    register struct cvobj *object;
  210.         for (object = &(cvobj[1]); object->desc != NULL ; object++ )
  211.         {    object->conn1.where = object->conn2.where = LOST ;
  212.             object->prop = object->iprop ;
  213.             object->conn1.link  = object->conn2.link  = NULL ;
  214.             object->conn1.who   = object->conn2.who   = object ;
  215.             object->conn1.where = object->conn2.where = LOST ;
  216.         }
  217.         lastobj = object - 1 ;
  218.     }
  219.  
  220.     {    register struct cvloc *curloc;
  221.  
  222.         for (curloc = &cvloc[1]; curloc->travel != NULL; curloc++ )
  223.         {    register struct cvtrav *curtrv;
  224.             curloc->abb = 0;
  225.             curloc->atloc.link = NULL ;
  226.             curtrv = curloc->travel ;
  227.             if (curtrv->word == 1)
  228.                 curloc->flags = C_FORCED ;
  229.         }
  230.     }
  231.  
  232. /************
  233.  * set up the location arrays to that objects are at their indicated
  234.  * places.  We use drop, which puts things on the head of the list, so
  235.  * we run this backwards.  Things with two locations are dropped twice,
  236.  * and since these are normally best described last, we do them first.
  237.  ************/
  238.     {    register struct cvobj *object;
  239. #define    ILOC(obj)    (((obj)->iloc) ? (&(cvloc[(obj)->iloc])) : LOST )
  240.         for (object = lastobj; ONUM(object); object--)
  241.         {    if (object->iloc2 > 0 )
  242.             {    move2(object,&(cvloc[object->iloc2]));
  243.                 move(object, ILOC(object) );
  244.             }
  245.         }
  246.  
  247.         for (object = lastobj; ONUM(object); object-- )
  248.         {    if (object->iloc2 <= 0 )
  249.             {    move(object, ILOC(object) );
  250.                 object->conn2.where = object->iloc2 ? FIXED : LOST;
  251.             }
  252.         }
  253.     }
  254.  
  255. /*************************************************************************
  256.  * clear the hint stuff.  loc is how long he's been at a loc with the
  257.  * cond bit set.  hinted is true if the hint has already been given.
  258.  *************************************************************************/
  259.     {    register struct hint *hint;
  260.  
  261.         for (hint = hints; hint->turns >= 0; ++hint)
  262.         {    hint->lc = 0;
  263.             hint->hinted = FALSE ;
  264.         }
  265.     }
  266.  
  267. /*************************************************************************
  268.  * initialize the monsters.
  269.  * they are all known generically as dwarves because they all move like
  270.  * dwarves, though the adventurer never really knows this.
  271.  *
  272.  * dloc is current location
  273.  * oloc is old location
  274.  * dseen is a flag.  If on, this dwarf has the adventurer in sight and
  275.  *    is in hot pursuit.
  276.  * dflag indicates the level of activity:
  277.  *    0    no monster stuff yet (wait until pool hall is reached)
  278.  *    1    no monsters met yet (thus, no axe)
  279.  *    2    have axe, but no knives yet.  most dwarves moving.
  280.  *    3    first knives thrown (first set always miss)
  281.  *    3+    dwarves are mad (and thus more accurate)
  282.  * some dwarves don't look much like dwarves
  283.  *    1    is grendl the spider
  284.  *    2    is the dragon
  285.  *    3    is the king
  286.  *     4    is the djinni
  287.  *     5    is the kobold
  288.  *    6    is the bugbear
  289.  *    7    is the unicorn
  290.  *    8    is the giant orc
  291.  *    9    is the balrog
  292.  *    10-15    are just dwarves
  293.  *    16    is the pirate.
  294.  *    17    is *you*
  295.  * no two of the initial locations for 10-16 are adjacent.  The others
  296.  * only start as part of a pre-set encounter.
  297.  *************************************************************************/
  298.  
  299.     dflag = 0;
  300.  
  301.     {    register struct monster *cre;
  302.  
  303.         for (cre = orcs ; (cre->iloc) != -1; cre++) {
  304.             cre->dloc = &cvloc[cre->iloc] ;
  305.             cre->dseen = FALSE ;
  306.         }
  307.     }
  308.  
  309. /*************************************************************************
  310.  * 'tally' keeps track of how many treasures are yet to be found so we
  311.  * know when to close the cave.  'tally2' keeps track of how many can
  312.  * never be found because the adventurer klutzed out (e.g. lost the
  313.  * scroll in the maze).
  314.  * ***** tally2 is not yet implemented *****
  315.  * the objects must be assigned numbers in the following order
  316.  *    treasures
  317.  *    end-game weapons
  318.  *    artifacts in outer cave
  319.  *    other objects
  320.  *************************************************************************/
  321.     tally = tally2 = 0 ;
  322.     
  323.     {    register struct cvobj *object;
  324.         for (object = MINTRS ; object != ENDTRS ; ++object ) {
  325.             object->prop = -1 ;
  326.             ++tally ;
  327.         }
  328.     }
  329.  
  330.     BATTER->prop = -1 ;
  331.     oldlc2 =
  332.     knfloc = LOST ;
  333.  
  334.     inorth =        /* # of times he said NORTH instead of N */
  335.     detail =        /* # of times we said "not allowed . .  */
  336.     numdie =        /* # of times he died so far */
  337.     holding =        /* # objects he's carrying */
  338.     dkill =            /* # of dwarves killed */
  339.     turns =
  340.     nxtchr = 0;
  341.  
  342.     abbnum = 5 ;        /* how often he gets long description */
  343.  
  344.     clock1 = 30 ;        /* time from last treasure to closing */
  345.     clock2 = 50 ;        /* time from closing to closed */
  346.  
  347.     bonus =            /* gets bonus for correct finish */
  348.     closing =        /* are we closing? */
  349.     panic =            /* has he panicked */
  350.     closed =
  351.     gaveup =
  352.     scoring =
  353.     mltcmd =
  354.     samvrb =
  355.     finish =
  356.     lmwarn = FALSE ;
  357.  
  358.     {    register int i;
  359.         for (i=0 ; i<=4; ++i)
  360.             if ( rmsg[2*i+81] != NULL ) maxdie = i+1 ;
  361.     }
  362.  
  363.     saved = saved == 1 ? -1 : 2 ;
  364. /*************************************************************************
  365.  * OK, we're close now.  Get a couple more things set.
  366.  *************************************************************************/
  367.     demo = FALSE;        /* everyone's a class 1 user here */
  368.     motd(FALSE);        /* message of the day? */
  369.     hints[3].hinted = yes(65,1,0);    /* instructions? */
  370.     newloc = &(cvloc[1]) ;        /* start here */
  371.     oldloc = DEAD ;        /* make lint happy */
  372.     wzdark = FALSE ;
  373.     setup = 3 ;            /* in full swing */
  374.     limit = hints[3].hinted ? 1000 : 330 ;
  375.     juggl2(O_GATE);
  376.     juggle(BEAR);
  377.     juggle(HANG);
  378.  
  379. /*************************************************************************
  380.  * begin the real stuff
  381.  *************************************************************************/
  382.  
  383.     dodwarf();
  384.     while (!finish)  /* motion loop */
  385.     {    register struct cvobj *object;
  386.         int verb, oldvrb, obj ;
  387.  
  388.         blklin = TRUE ;
  389.         if (loc == DEAD) {die(); continue; } ;
  390.         if (FORCED(loc)) {
  391.             showroom();
  392.             verb = 1; /* for the benefit of a later switch */
  393.         } else { /* motion not forced */
  394.             if (DARK) {
  395.                 if (wzdark && PCT(35)) {
  396.                     rspeak(23);
  397.                     oldlc2 = loc;
  398.                     {die(); continue; };
  399.                 } else rspeak(16);
  400.             } else { /* not dark: describe objects found here */
  401.                 register struct conn *curcon, *lastcon;
  402.                 if (DARKRM)
  403.                     pspeak(UNICRN,6); /* that must be the light */
  404.                 showroom();
  405.                 if (TOTING(BOAT)) pspeak(BOAT,BOAT->prop);
  406.                 if (TOTING(RUG) && (RUG->prop == 1)) pspeak(RUG,1);
  407.                 curcon = &(loc->atloc);
  408.                 while (curcon->link != NULL) {
  409.                     register struct cvobj *adobj;
  410.                     register int i;
  411.                     lastcon = curcon;
  412.                     curcon = curcon->link ;
  413.                     adobj = curcon->who ;
  414.                     if (curcon->where != loc) bug(32);
  415.                     if (adobj->prop < 0) {
  416.                         adobj->prop = adobj->iprop;
  417.                         if (IFTREAS(adobj)) --tally;
  418.                         if ((tally == tally2) && tally)
  419.                             limit = MIN(limit,35);
  420.                     }
  421.                     i = adobj->prop ;
  422. /* handle special cases */
  423. /* tell about the inside of the gate, if the dummy's there */
  424.                     if ((adobj == O_GATE)
  425.                         && (O_GATE->conn2.where == loc))
  426.                         i = 1;
  427. /* funny way to tell what happened to the container */
  428.                     if (((adobj == CUP) || (adobj == BOTTLE))
  429.                         && (adobj->conn2.where == FIXED)
  430.                         && (BEAR->prop == 0)
  431.                         && (HERE(BEAR)) ) i = 13 ;
  432.                     pspeak(adobj,i) ;
  433.                     blklin = FALSE ;
  434. /* seeing the poo close up means there are footprints in it */
  435.                     if (adobj == CRAP) adobj->prop = 1 ;
  436. /* remove ranger from gate after the first time he's seen */
  437.                     if (adobj == RICK) {
  438.                         RICK->prop++ ;
  439.                         destry(RICK);
  440.                         curcon = lastcon;
  441.                     }
  442.                 } /* end showing adobjs */    
  443.             } /* end describing objects here */
  444.             goto okay;
  445.  
  446. /* stuff for when you can't find the indicated object (it may be too dark)
  447. */
  448. dark:        ;
  449.             capchk(word1);    /* capitalize some proper nouns */
  450.             (void) printf("I see no %s here.\n",word1);
  451.             mltcmd = FALSE ;
  452. /* loop here when you say "okay" and such -- less dangerous place than
  453.  * most, but still must watch the skeleton, the lamp, etc.
  454.  */
  455. okay:            ;
  456.             blklin = TRUE ;
  457. /* if the skeleton's active, it can kill you */
  458.             if (SKELTN->prop == 1) {
  459.                 if (PCT(25)) {
  460.                     rspeak(102);
  461.                     oldlc2 = loc ;
  462.                     {die(); continue; };
  463.                 }
  464.                 rspeak(101);
  465.             }
  466.  
  467. miss:        if (TOTING(MEDAL) && (loc->flags & SECRET)) rspeak(112);
  468.  
  469.             if ((loc->flags & RANGER)
  470.                 && (RICK->prop == 0)
  471.                 && (DAM->prop == 0)
  472.                 && (PCT(25) || (loc->atloc.link != NULL))
  473.                 ) {
  474.                 pspeak(RICK,6);
  475.                 RICK->prop = 3;
  476.                 destry(RICK);
  477.                 loc = &(cvloc[O_GATE->iloc]);
  478.                 break;
  479.             }
  480.  
  481. /* finds you hanging in there? */
  482.             if ((LNUM(loc) == 144) && PCT(25)) {
  483.                 rspeak(217) ;
  484.                 if (PCT(50)) rspeak(218);
  485.             }
  486.  
  487. /* when we don't understand, we come back here for a relatively safe retry.
  488.  */
  489. huh:        oldvrb = verb ;
  490.             verb = 0;
  491. newobj:        obj = 0;
  492.             object = NULL ;
  493. /* if he left off the verb, we let him come back here to say it.
  494.  */
  495. getvrb:            ;
  496. /* check if this place is eligible for any hints.  If the sucker has been
  497.  * here long enough, perform the help section.
  498.  */
  499.             {    register struct hint *hint;
  500.                 for (hint = hints+4; hint->turns != -1; ++hint) {
  501.                     if (!(hint->hinted)) {
  502.                         if (!(loc->flags & hint->bit)) hint->lc = -1 ;
  503.                         ++(hint->lc);
  504.                         if (hint->lc >= hint->turns) dohint(hint);
  505.                     }
  506.                 }
  507.             } /* end of hint block */
  508.  
  509. /* if closing this turn, check for any objects being toted with prop<0.
  510.  * set the prop to -1-prop.  This way objects won't be described until
  511.  * they've been picked up and put down separate from their respective
  512.  * piles.  Don't let any of this happen unless well into the cave.
  513.  */
  514.             if (closed) {
  515.                 register struct cvobj *adobj;
  516.                 for (adobj=cvobj;adobj->desc != NULL; ++adobj)
  517.                     if (TOTING(adobj) && (adobj->prop < 0))
  518.                         adobj->prop = -adobj->prop - 1;
  519.             }
  520.  
  521.             wzdark = DARK ;
  522.  
  523.             if ((knfloc != LOST) & (knfloc != loc)) knfloc = FIXED;
  524.  
  525. /* get input */
  526.             getin() ; /* set word1, word2 */
  527.  
  528.             if (!(turns++)
  529.                 && !strcmp("magic",word1)
  530.                 && !strcmp("mode",word2) )
  531.             {    maint(argv[0]); }
  532.             
  533. /* demo games are ended by the wizard */
  534.             if (demo && (turns >= SHORT))
  535.             {    mspeak(1);
  536.                 {finish = TRUE; continue; };
  537.             }
  538.  
  539.             if (samvrb) verb = oldvrb ;
  540.  
  541.             if ((verb == SAY) && (word2 != NULL)) verb = 0 ;
  542.             if (verb == SAY) goto process ;
  543.  
  544. /* detect closing, closed, etc */
  545.             if ((LNUM(loc) >= 31) && !tally && !(--clock1))
  546.             {    register struct monster *cre;
  547.  
  548.                 DOOR->prop = 0;
  549.                 if (O_GATE->prop != 2) O_GATE->prop = 3;
  550.                 for (cre = orcs; cre->iloc != -1; ++cre)
  551.                 {    cre->dloc = DEAD ;
  552.                     cre->dseen = FALSE ;
  553.                 }
  554.                 if (BEAR->prop) destry(BEAR);
  555.                 if (CHAIN->prop == 2) CHAIN->prop = 1;
  556.                 AXE->prop = 0 ;
  557.                 AXE->conn2.where = DEAD;
  558.                 rspeak(129);
  559.                 clock1 = -1;
  560.                 closing = TRUE ;
  561.             }
  562.  
  563.             if (clock1 < 0 && !(--clock2))
  564.             {    register struct cvobj *curobj;
  565.                 loc = oldloc = newloc = OFFICE ;
  566.                 /* Put him there "naked" except for compass */
  567.                 for (curobj=cvobj; curobj->desc != NULL; ++curobj) {
  568.                     if (TOTING(curobj) && curobj != COMPASS)
  569.                         destry(curobj);    
  570.                 }
  571.                 move(AXE,REPOS);
  572.                 rspeak(132);
  573.                 closed = TRUE;
  574.                 {locchg(); continue; };
  575.             }
  576.  
  577. /* one way to get to the end of the game is for the lamp to give out.
  578.  * When it gets close, we warn him.  If the lamp and fresh batteries are
  579.  * handy, we replace the batteries for him.  Otherwise, he may be in
  580.  * trouble, depending on where he is.
  581.  */
  582.             if ((LAMP->prop == 1)
  583.                 && (--limit <= 30)
  584.                 && HERE(BATTER)
  585.                 && !(BATTER->prop)
  586.                 && HERE(LAMP) )
  587.             {    rspeak(188);
  588.                 BATTER->prop = 1 ;
  589.                 if (TOTING(BATTER)) move(BATTER,loc) ;
  590.                 limit += 500 ;
  591.                 lmwarn = FALSE ;
  592.             }
  593.  
  594. /* if lamp runs out */
  595.             if (!limit)
  596.             {    limit = -1;
  597.                 LAMP->prop = 0 ;
  598.                 if (HERE(LAMP)) rspeak(184) ;
  599.             }
  600.  
  601. /* if it's dark and he's outside the cave proper, he just gives up */
  602.             if ((limit < 0) && (LNUM(loc) <= 30))
  603.             {    rspeak(185) ;
  604.                 gaveup = TRUE;
  605.                 {finish = TRUE; continue; } ;
  606.             }
  607.  
  608. /* give warning about dim lamp */
  609.             if ((limit <= 30) && HERE(LAMP) && !lmwarn)
  610.             {    lmwarn = TRUE ;
  611.                 if ((BATTER->prop == 1) || (BATTER->conn1.where == LOST))
  612.                     rspeak(189);
  613.                 else if (BATTER->prop == 0)
  614.                     rspeak(183);
  615.                 else
  616.                     rspeak(187);
  617.             }
  618.  
  619. /* now for the real work: we have to figure out what he means by what
  620.  * he just said.
  621.  */
  622.             for ( ; word1 != NULL; word1=word2, word2=NULL)
  623.             {    register int i;
  624.  
  625.                 if (!strcmp(word1,"north"))
  626.                     if (++inorth == 10) rspeak(17);
  627.                 i = vocab(word1,-1);
  628.                 if (i == -1)
  629.                 {    what(TRUE); /* some form of not understanding */
  630.                     goto huh;
  631.                 }
  632. /* if he says ENTER, he may not really go anywhere because of some special
  633.  * cases.  Going into the water just gets him wet.  Going into the boat
  634.  * is treated as "take boat", so we change his verb.
  635.  */
  636.                 if ((i == ENTER)
  637.                     && (word2 != NULL))
  638.                 {    if (!strcmp(word2,"stream")
  639.                         || !strcmp(word2,"water")
  640.                         || !strcmp(word2,"river") )
  641.                     {    if (LIQLOC(loc) == _WATER)
  642.                             rspeak(70); /* wet feet! */
  643.                         else
  644.                             rspeak(43); /* Where? */
  645.                         goto okay ; /* maybe this should just be moved */
  646.                     }
  647.                     else if (!strcmp(word2,"boat"))
  648.                     {    obj = _BOAT;
  649.                         object = OBJ(obj) ;
  650.                         i = TAKE;
  651.                     }
  652.                 }
  653.  
  654.                 switch(i/1000)
  655.                 {
  656. /* this is one of the big holes in the parser here.  Motion words are
  657.  * hardly checked for syntax at all.  The object is usually not even
  658.  * looked at, if given.  There are just a few special cases, and they
  659.  * do not go through the normal vocabulary stuff.
  660.  */
  661.                 case 0: /* motion word */
  662.                     if (obj || (verb && (verb != WALK))) 
  663.                         {what(FALSE); goto huh; }
  664.                     if ((i == OUT) && (!strcmp(word2,"boat")))
  665.                     {    i = DROP ; } /* deal with word ambiguity here */
  666.                     if (i == OUT
  667.                         && TOTING(BOAT)
  668.                         && (word2 == NULL || !strcmp(word2,""))
  669.                         && obj == 0) {
  670.                         i = DROP ;
  671.                         object = OBJ(obj = _BOAT);
  672.                     }
  673.                     verb = i ; /* this sets dispatch switch */
  674.                     break;
  675.  
  676. /* for objects, we make sure that there are not two objects being named,
  677.  * and that the object is here.  Also, if there's another word, we clear
  678.  * 'verb' which may have been set by the operation of 'samvrb'.
  679.  */
  680.                 case 1: /* object */
  681.                     oword = word1;
  682.                     if (obj != i)
  683.                     {    if (obj
  684.                             || (verb && (word2 != NULL)))
  685.                         {    what(FALSE); /* don't understand */
  686.                             goto huh;
  687.                         }
  688.                     }
  689.                     object = OBJ(obj = i) ;
  690.                     if (word2 != NULL) verb = 0; /* defeat samvrb */
  691.  
  692.                     if ((object->conn2.where != loc)
  693.                         && !HERE(object)) /* object maybe not here */
  694.                     {    register int flag;
  695.                         flag = FALSE ;
  696.                         if ((obj == _DWARF) && (dflag > 1))
  697.                         {    register struct monster *cre;
  698.                             for (cre = orcs; cre->iloc >= 0; ++cre)
  699.                             {    if (cre->dloc == loc)
  700.                                 {    flag = TRUE ;
  701.                                     break;
  702.                                 }
  703.                             }
  704.                         }
  705.                         if (flag
  706.                             || (obj == LIQLOC(loc))
  707.                             || ((obj == LIQ(BOTTLE)) && HERE(BOTTLE))
  708.                             || ((obj == LIQ(CUP))    && HERE(CUP)   )
  709.                             || ((object == SPIDER)
  710.                                 && (GRENDL->dloc == loc))
  711.                             || ((object == DRAGON)
  712.                                 && (PUFF->dloc == loc))
  713.                             || ((object == DJINN)
  714.                                 && (JEANNIE->dloc == loc))
  715.                             || ((object == KOBOLD)
  716.                                 && (SLASHER->dloc == loc))
  717.                             || ((object == BALROG)
  718.                                 && (BALLY->dloc == loc))
  719.                             || ((object == SELF)
  720.                                 && (ME->dloc == loc))
  721.                             )
  722.                             ; /* okay to keep going */
  723.                         else if ((object == KNIFE)
  724.                             && (knfloc == loc))
  725.                         {    knfloc = LOST;
  726.                             rspeak(116); /* sorry about them knives */
  727.                             goto okay ;
  728.                         } else if ((object == ROPE)
  729.                             && (HERE(ROPE2)))
  730.                         {    object = ROPE2 ;
  731.                             ; /* substitute the "other" rope */
  732.                         } else if ((object == ROPE)
  733.                             && (HERE(EROPE)))
  734.                         {    object = EROPE ;
  735.                         } else if ((object == ROPE)
  736.                             && (HERE(EROPE2)))
  737.                         {    object = EROPE2;
  738.                         } else if ( (word2 == NULL)
  739.                             && ((verb == FIND)
  740.                                 || (verb == INVENT)
  741.                                 || (verb == DESCRB)
  742.                                 || (verb == TOUCH) ) )
  743.                         {    ; /* allow questions about things not here */
  744.                         } else {
  745.                             if (!verb && (word2 == NULL))
  746.                             /* this test is sensitive to verb funnies */
  747.                             {    register int k;
  748.                                 if ((k=vocab(word1,3)) > 0)
  749.                                 {    rspeak(k%1000); /* word has msg num */
  750.                                     goto okay ;
  751.                                 }
  752.                             }
  753.                             goto dark;
  754.                         }
  755.                     } /* end of the case the object is not here */
  756.  
  757.                     if ((object == TOMB) && (HELM->prop))
  758.                         object = HELM ; /* actually a synonym */
  759.                     if (word2 != NULL) break;
  760.                     if (verb) break ;
  761.                     {    register int k;
  762.                         if ((k=vocab(word1,3)) >0)
  763.                         {    rspeak(k%1000);    /* word has msg num in it */
  764.                             goto okay;
  765.                         }
  766.                     }
  767.                     capchk(word1);    /* capitialize some proper nouns */
  768.                     (void) printf(
  769. "What do you want to do with the %s?",word1);
  770.                     mltcmd = FALSE ;
  771.                     goto getvrb ;
  772.  
  773.                 case 2: /* action (verb) */
  774.                     vword = word1;
  775.                     if ((verb == TAKE)
  776.                         && ((i == INVENT)
  777.                             || (i == verb)))
  778.                     {    verb = 0; /* destroy old verb */
  779.                     }
  780.                     if (verb && !obj && (word2 == NULL))
  781.                     {    what(FALSE); /* two verbs */
  782.                         goto huh;
  783.                     }
  784.                     if (word2 != NULL) {obj = 0 ; object = NULL ; }
  785.                     verb = i;
  786.                     if (word2 != NULL)
  787.                         if (verb == SAY)
  788.                         {    obj = 1;
  789.                             goto process;
  790.                         }
  791.                     break;
  792.  
  793.                 case 3: /* special (just gets message) */
  794.                     verb = i ; /* this sets dispatch switch */
  795.                     break;
  796.                 } /* end of word-type switch */
  797.             } /* end of word analysis */
  798.  
  799.         } /* end of getting new instructions (motion not forced) */
  800. process:
  801.         switch (verb/1000)
  802.         {
  803.         case 0: /* motion verb */
  804.             newloc = moveme(loc,verb) ;
  805.             locchg();
  806.             continue ;
  807.  
  808.         case 2: /* true verb */
  809.             if (verb == SAY) {
  810.                 if (word2 != NULL) word1 = word2;
  811.                 obj = vocab(word1,-1); /* what would happen? */
  812.                 if (obj == HOPE || obj == BANIS || obj == MISFO) {
  813.                     verb = obj; obj = 0; object = NULL;
  814.                 } else {
  815.                     printf("Okay, \"%s\".\n",word1);
  816.                     goto okay;
  817.                 }
  818.             }
  819.             switch (cvact(verb,obj,object))
  820.             {
  821.             case S_okay: goto okay;
  822.             case S_miss: goto miss;
  823.             case S_move: break;
  824.             case S_obj: goto newobj;
  825.             case S_what: *vword = toupper(*vword);
  826.                 printf("%s what?\n",vword);
  827.                 mltcmd = FALSE;
  828.                 goto newobj;
  829.             case S_light: if (!DARK && wzdark) continue;
  830.                 goto okay;
  831.             case S_show: continue;
  832.             case S_dark: goto dark;
  833.             default: bug(40);
  834.             }
  835.             locchg();
  836.             continue;
  837.  
  838.         case 3: /* magic word */
  839.             rspeak(verb%1000);
  840.             goto okay;
  841.  
  842.         default: /* how could this be? */
  843.             bug(1);
  844.         }
  845.     } /* end of motion loop */
  846.  
  847.     getscore();
  848.     (void) printf("\nYou scored %d out of a possible %d, using %d turns.\n",
  849.         score,mxscore,turns);
  850.     {    register struct cmsg *cmsg;
  851.         for (cmsg = ctext;cmsg->score != -1; ++cmsg) ;
  852.         for (--cmsg; cmsg - ctext; --cmsg) {
  853.             if (cmsg->score <= 0) cmsg->score += mxscore ;
  854.             if (cmsg->score <= score) break;
  855.         }
  856.         (void) fputs(cmsg->msg,stdout);
  857.         if ((cmsg+1)->score == -1) {
  858.             (void) fputs("To achieve the next higher rating would be a\
  859.  neat trick!\n\n Congratulations!\n",stdout);
  860.         }else{
  861.             (void) printf("To achieve the next higher rating, you need %d \
  862. more point%s.\n",(cmsg+1)->score - score, ((cmsg+1)->score - score > 1) ?
  863.                 "s" : "");
  864.         }
  865.     } /* end of figuring the appropriate message */
  866.  
  867.     puts("\nTouch ENTER to continue.\n");
  868.     {    auto char answer[5];
  869.         fgets(answer,4,stdin);
  870.     }
  871. }
  872.